#include "KeySearchResultDlg.h"

#include <core/StyleMgr.h>
#include <qjsonarray.h>
#include <qjsondocument.h>

#include <QApplication>
#include <QBitmap>
#include <QBoxLayout>
#include <QFocusEvent>
#include <QListWidget>
#include <QPainter>
#include <QScrollBar>
#include <iostream>

#include "../KeySearchWidget.h"
#include "KeySearchResultDlg.h"

#if WIN32
#include <qt_windows.h>
#endif

KeySearchResultDlg::KeySearchResultDlg(KeySearchWidget* parent, int itemHeight)
    : QWidget(parent), m_itemHeight(itemHeight), m_host(parent) {
  setWindowFlags(Qt::FramelessWindowHint | Qt::ToolTip);
  setStyleSheet(
      "border-top:1px solid "
      "#142222;\nborder-radius:4px;\nbackground:#193D37\n");

  QVBoxLayout* layout = new QVBoxLayout();
  layout->setContentsMargins(0, 0, 0, 0);
  layout->setSpacing(0);

  m_list = new QListWidget(this);

  QString style =
      QString(
          "QListWidget::item:hover{background:#%1;}"
          "QListWidget{color:#%2;font:13px Microsoft YaHei;}" /*font-weight:bold;*/
          "QListWidget{background:#%3;}")
          .arg(StyleMgr::instance().color("Hover").rgb(), 0, 16)
          .arg(StyleMgr::instance().color("TextNormal").rgb(), 0, 16)
          .arg(StyleMgr::instance().color("ElementBackground").rgb(), 0, 16);
  m_list->setStyleSheet(style);

  QScrollBar* vetScroll = new QScrollBar(this);
  vetScroll->hide();
  vetScroll->setValue(0);
  vetScroll->setFixedWidth(8);

  m_list->setVerticalScrollBar(vetScroll);
  layout->addWidget(m_list);
  setLayout(layout);
}

void KeySearchResultDlg::setListItemDelegate(
    QAbstractItemDelegate* itemDelegate) {
  m_list->setItemDelegate(itemDelegate);
}

void KeySearchResultDlg::setMaxHeight(int h) { setMaximumHeight(h); }

void KeySearchResultDlg::setWidth(int w) { setFixedWidth(w); }

void KeySearchResultDlg::showEvent(QShowEvent* event) {
  QWidget* p = dynamic_cast<QWidget*>(parent());
  QPoint pos(0, p->height());
  pos = p->mapToGlobal(pos);
  move(pos);
  qApp->installEventFilter(this);
}

void KeySearchResultDlg::hideEvent(QHideEvent* event) {
  qApp->removeEventFilter(this);
  m_host->resultHide();
  if (m_bAutoKillFocus) {
    m_host->clearEditFocus();
    m_host->foucsChanged(false);
  }
}

bool KeySearchResultDlg::eventFilter(QObject* watched, QEvent* e) {
  switch (e->type()) {
    case QEvent::Close:  // For QTBUG-55523 (QQC) specifically: Hide tooltip
                         // when windows are closed
      hide();
      break;
    case QEvent::FocusOut: {
      if (!underMouse()) hide();
      break;
    }
    case QEvent::ApplicationStateChange:
      // hide();
      break;
    case QEvent::MouseButtonPress:
    case QEvent::MouseButtonDblClick: {
      if (!this->underMouse() &&
          !static_cast<QWidget*>(parent())->underMouse()) {
        hide();
#if WIN32
        ::SetFocus(nullptr);
#endif
      } else if (e->type() == QEvent::MouseButtonDblClick) {
        if (m_list->currentItem() != nullptr) {
          QVariant var = m_list->currentItem()->data(Qt::UserRole);
          QJsonArray var_arr = var.toJsonArray();
          QString str = var_arr[0].toString();
          if (var_arr[0] != "") {
            m_host->searchEngine()->onResultSelected(str);
          }
        }

        hide();
      }
      break;
    }
    case QEvent::KeyPress: {
      QKeyEvent* keyE = static_cast<QKeyEvent*>(e);
      if (keyE->key() == Qt::Key_Up) {
        selectPreviousItem(m_list->currentRow());
        return true;
      } else if (keyE->key() == Qt::Key_Down) {
        selectNextItem(m_list->currentRow());
        return true;
      } else if (keyE->key() == Qt::Key_Enter ||
                 keyE->key() == Qt::Key_Return) {
        QString strResult = "";
        if (m_list->currentItem() != nullptr) {
          QVariant var = m_list->currentItem()->data(Qt::UserRole);
          QJsonArray var_arr = var.toJsonArray();
          QString str = var_arr[0].toString();
          if (var_arr[0] != "") {
            strResult = str;
          }
        } else if (m_list->count() == 1) {
          QVariant var = m_list->item(0)->data(Qt::UserRole);
          QJsonArray var_arr = var.toJsonArray();
          QString str = var_arr[0].toString();
          if (var_arr[0] != "") {
            strResult = str;
          }
        }
        if (!strResult.isEmpty() || !m_bAutoSelect)
          m_host->searchEngine()->onResultSelected(strResult);
        hide();
        return true;
      }
      break;
    }
    default:
      break;
  }
  return false;
}

void KeySearchResultDlg::selectNextItem(int index) {
  while (++index < m_list->count()) {
    QListWidgetItem* item = m_list->item(index);
    if ((item->flags() & Qt::ItemIsSelectable) == 0) continue;
    m_list->setCurrentItem(item);
    break;
  }
}

void KeySearchResultDlg::selectPreviousItem(int index) {
  while (--index >= 0) {
    QListWidgetItem* item = m_list->item(index);
    if ((item->flags() & Qt::ItemIsSelectable) == 0) continue;
    m_list->setCurrentItem(item);
    break;
  }
}

void KeySearchResultDlg::onResultReached(QJsonArray data) {
  m_list->clear();

  if (data.empty()) {
    hide();
    return;
  }

  int height = m_itemHeight * data.count();
  if (height > maximumHeight())
    height = m_itemHeight * (maximumHeight() / m_itemHeight);
  resize(width(), height + 1);

  for (QJsonValue v : data) {
    QListWidgetItem* item = new QListWidgetItem();
    item->setData(Qt::UserRole, v);
    QJsonObject dataJson = v.toObject();

    if (!dataJson.isEmpty() && !dataJson.value("sel").isUndefined() &&
        dataJson["sel"].toBool() == false) {
      item->setFlags(item->flags() & (~Qt::ItemFlag::ItemIsSelectable));
    }

    m_list->addItem(item);
  }
  if (m_bAutoSelect) selectNextItem();
  show();
}

void KeySearchResultDlg::paintEvent(QPaintEvent* event) {
  // 设置关于窗体为圆角
  QBitmap bmp(this->size());
  bmp.fill();
  QPainter p(&bmp);
  p.setPen(Qt::NoPen);
  p.setBrush(Qt::black);
  p.drawRoundedRect(bmp.rect(), 5, 5);
  setMask(bmp);
}